using System;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using Home.Site.Models.WebUI;

namespace Home.Site.Models.DataLayer
{
    public class ReviewRepository : IReviewRepository
    {
        readonly PromikeDBEntities context = new PromikeDBEntities();

        public IQueryable<Review> All
        {
            get { return context.Reviews; }
        }

        public IQueryable<Review> AllIncluding(params Expression<Func<Review, object>>[] includeProperties)
        {
            IQueryable<Review> query = context.Reviews;
            foreach (var includeProperty in includeProperties)
            {
                query = query.Include(includeProperty);
            }
            return query;
        }

        public Review Find(int id)
        {
            return context.Reviews.Find(id);
        }

        public void InsertOrUpdate(Review review)
        {
            if (review.idreview == default(int))
            {
                // New entity
                context.Reviews.Add(review);
            }
            else
            {
                // Existing entity
                context.Entry(review).State = EntityState.Modified;
            }
        }

        public void Delete(int id)
        {
            var review = context.Reviews.Find(id);
            context.Reviews.Remove(review);
        }

        public void Save()
        {
            context.SaveChanges();
        }

        public IQueryable<Review> GetReviewByCategory(CategoryTypes type)
        {
            return context.Reviews.Where(r => r.CategoryID == (int)type && r.Visible).OrderByDescending(x=>x.idreview);
        }

        public Review[] GetLastReviewByCategory(CategoryTypes type, int count)
        {
            var model =
                context.Reviews.Where(r => r.CategoryID == (int)type && r.Visible).OrderByDescending(r => r.idreview).Take(count).ToArray();
            return model;
        }

        public Review Build(ReviewViewModel review)
        {
            return new Review
                {
                    Title = review.Title,
                    Author = review.Author,
                    CreateUser = review.Author,
                    CategoryID = review.CategoryID,
                    DatePublish = review.DatePublish,
                    FileName = review.FileName,
                    MainContent = review.MainContent,
                    MainImage = review.MainImage,
                    MiniContent = review.MiniContent,
                    ReviewCategory = review.ReviewCategory,
                    ReviewTags = review.ReviewTags,
                    TagID = review.TagID,
                    Visible = review.Visible                    
                };
        }

        public IQueryable<Review> FilterByTitle(CategoryTypes type, string searchText)
        {
            return context.Reviews
                .Where(x =>x.Visible && x.CategoryID == (int)type)
                .Where(x=>x.Title.Contains(searchText) 
                    || x.Author.Contains(searchText) 
                    || x.ReviewTags.Any(t=>t.TagName.Contains(searchText)) 
                    || x.MiniContent.Contains(searchText));
        }

        public IQueryable<Review> Sort(SortTypes sortType, CategoryTypes type, string order)
        {
            var reviews = context.Reviews.Where(x => x.Visible && x.CategoryID == (int) type);
            if (order == "asc")
            {
                switch (sortType)
                {
                    case SortTypes.Name:
                        return reviews.OrderBy(x => x.Title);
                    case SortTypes.Date:
                        return reviews.OrderBy(x => x.DatePublish);
                    case SortTypes.Author:
                        return reviews.OrderBy(x => x.Author);
                }
            }
            else
            {
                switch (sortType)
                {
                    case SortTypes.Name:
                        return reviews.OrderByDescending(x => x.Title);
                    case SortTypes.Date:
                        return reviews.OrderByDescending(x => x.DatePublish);
                    case SortTypes.Author:
                        return reviews.OrderByDescending(x => x.Author);
                }
            }
            return null;
        }

        public IQueryable<Review> GetReviewByUser(string user)
        {
            return context.Reviews.Where(r => r.CreateUser == user).OrderByDescending(r => r.idreview);
        }

        public IQueryable<ReviewCategory> GetCategories()
        {
            return context.ReviewCategories;
        }

        public void Dispose()
        {
            context.Dispose();
        }
    }
}